home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / daten / ispell / source / ispell.h < prev    next >
C/C++ Source or Header  |  1995-06-29  |  24KB  |  652 lines

  1. /*
  2.  * $Id: ispell.h 1.1 1995/06/23 20:22:31 nobody Exp nobody $
  3.  */
  4.  
  5. /*
  6.  * Copyright 1992, 1993, Geoff Kuenning, Granada Hills, CA
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  *
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All modifications to the source code must be clearly marked as
  19.  *    such.  Binary redistributions based on modified source code
  20.  *    must be clearly marked as modified versions in the documentation
  21.  *    and/or other materials provided with the distribution.
  22.  * 4. All advertising materials mentioning features or use of this software
  23.  *    must display the following acknowledgment:
  24.  *      This product includes software developed by Geoff Kuenning and
  25.  *      other unpaid contributors.
  26.  * 5. The name of Geoff Kuenning may not be used to endorse or promote
  27.  *    products derived from this software without specific prior
  28.  *    written permission.
  29.  *
  30.  * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND
  31.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  32.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33.  * ARE DISCLAIMED.  IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE
  34.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  38.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  39.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  40.  * SUCH DAMAGE.
  41.  */
  42.  
  43. /*
  44.  * $Log: ispell.h $
  45.  * Revision 1.1  1995/06/23  20:22:31  nobody
  46.  * Initial revision
  47.  *
  48.  * Revision 1.67  1995/01/03  19:24:12  geoff
  49.  * Get rid of a non-global declaration.
  50.  *
  51.  * Revision 1.66  1994/12/27  23:08:49  geoff
  52.  * Fix a lot of subtly bad assumptions about the widths of ints and longs
  53.  * which only show up on 64-bit machines like the Cray and the DEC Alpha.
  54.  *
  55.  * Revision 1.65  1994/11/02  06:56:10  geoff
  56.  * Remove the anyword feature, which I've decided is a bad idea.
  57.  *
  58.  * Revision 1.64  1994/10/25  05:46:18  geoff
  59.  * Add the FF_ANYWORD flag for defining an affix that will apply to any
  60.  * word, even if not explicitly specified.  (Good for French.)
  61.  *
  62.  * Revision 1.63  1994/09/16  04:48:28  geoff
  63.  * Make stringdups and laststringch unsigned ints, and dupnos a plain
  64.  * int, so that we can handle more than 128 stringchars and stringchar
  65.  * types.
  66.  *
  67.  * Revision 1.62  1994/09/01  06:06:39  geoff
  68.  * Change erasechar/killchar to uerasechar/ukillchar to avoid
  69.  * shared-library problems on HP systems.
  70.  *
  71.  * Revision 1.61  1994/08/31  05:58:35  geoff
  72.  * Add contextoffset, used in -a mode to handle extremely long lines.
  73.  *
  74.  * Revision 1.60  1994/05/17  06:44:15  geoff
  75.  * Add support for controlled compound formation and the COMPOUNDONLY
  76.  * option to affix flags.
  77.  *
  78.  * Revision 1.59  1994/03/15  06:25:16  geoff
  79.  * Change deftflag's initialization so we can tell if -t/-n appeared.
  80.  *
  81.  * Revision 1.58  1994/02/07  05:53:28  geoff
  82.  * Add typecasts to the the 7-bit versions of ichar* routines
  83.  *
  84.  * Revision 1.57  1994/01/25  07:11:48  geoff
  85.  * Get rid of all old RCS log lines in preparation for the 3.1 release.
  86.  *
  87.  */
  88.  
  89. #include <stdio.h>
  90.  
  91. #ifdef __STDC__
  92. #define P(x)    x
  93. #define VOID    void
  94. #else /* __STDC__ */
  95. #define P(x)    ()
  96. #define VOID    char
  97. #define const
  98. #endif /* __STDC__ */
  99.  
  100. #ifdef NO8BIT
  101. #define SET_SIZE    128
  102. #else
  103. #define SET_SIZE    256
  104. #endif
  105.  
  106. #ifdef AMIGA
  107. #include <proto/exec.h>
  108. #include <proto/rexxsyslib.h>
  109. #include "minrexx.h"
  110. #endif /* AMIGA */
  111.  
  112. #define MASKSIZE    (MASKBITS / MASKTYPE_WIDTH)
  113.  
  114. #ifdef lint
  115. extern void    SETMASKBIT P ((MASKTYPE * mask, int bit));
  116. extern void    CLRMASKBIT P ((MASKTYPE * mask, int bit));
  117. extern int    TSTMASKBIT P ((MASKTYPE * mask, int bit));
  118. #else /* lint */
  119. /* The following is really testing for MASKSIZE <= 1, but cpp can't do that */
  120. #if MASKBITS <= MASKTYPE_WIDTH
  121. #define SETMASKBIT(mask, bit) ((mask)[0] |= (MASKTYPE) 1 << (bit))
  122. #define CLRMASKBIT(mask, bit) ((mask)[0] &= (MASKTYPE) ~(1 << (bit)))
  123. #define TSTMASKBIT(mask, bit) ((mask)[0] & ((MASKTYPE) 1 << (bit)))
  124. #else
  125. #define SETMASKBIT(mask, bit) \
  126.             ((mask)[(bit) / MASKTYPE_WIDTH] |= \
  127.               (MASKTYPE) 1 << ((bit) & (MASKTYPE_WIDTH - 1)))
  128. #define CLRMASKBIT(mask, bit) \
  129.             ((mask)[(bit) / MASKTYPE_WIDTH] &= \
  130.               ~((MASKTYPE) 1 << ((bit) & (MASKTYPE_WIDTH - 1))))
  131. #define TSTMASKBIT(mask, bit) \
  132.             ((mask)[(bit) / MASKTYPE_WIDTH] & \
  133.               ((MASKTYPE) 1 << ((bit) & (MASKTYPE_WIDTH - 1))))
  134. #endif
  135. #endif /* lint */
  136.  
  137. #if MASKBITS > 64
  138. #define FULLMASKSET
  139. #endif
  140.  
  141. #ifdef lint
  142. extern int    BITTOCHAR P ((int bit));
  143. extern int    CHARTOBIT P ((int ch));
  144. #endif /* lint */
  145.  
  146. #if MASKBITS <= 32
  147. # ifndef lint
  148. #define BITTOCHAR(bit)    ((bit) + 'A')
  149. #define CHARTOBIT(ch)    ((ch) - 'A')
  150. # endif /* lint */
  151. #define LARGESTFLAG    26    /* 5 are needed for flagfield below */
  152. #define FLAGBASE    (MASKTYPE_WIDTH - 6)
  153. #else
  154. # if MASKBITS <= 64
  155. #  ifndef lint
  156. #define BITTOCHAR(bit)    ((bit) + 'A')
  157. #define CHARTOBIT(ch)    ((ch) - 'A')
  158. #  endif /* lint */
  159. #define LARGESTFLAG    (64 - 6) /* 5 are needed for flagfield below */
  160. #define FLAGBASE    (MASKTYPE_WIDTH - 6)
  161. # else
  162. #  ifndef lint
  163. #define BITTOCHAR(bit)    (bit)
  164. #define CHARTOBIT(ch)    (ch)
  165. #  endif /* lint */
  166. #define LARGESTFLAG    MASKBITS /* flagfield is a separate field */
  167. #define FLAGBASE    0
  168. # endif
  169. #endif
  170.  
  171. /*
  172. ** Data type for internal word storage.  If necessary, we use shorts rather
  173. ** than chars so that string characters can be encoded as a single unit.
  174. */
  175. #if (SET_SIZE + MAXSTRINGCHARS) <= 256
  176. #ifndef lint
  177. #define ICHAR_IS_CHAR
  178. #endif /* lint */
  179. #endif
  180.  
  181. #ifdef ICHAR_IS_CHAR
  182. typedef unsigned char    ichar_t;    /* Internal character */
  183. #define icharlen(s)    strlen ((char *) s)
  184. #define icharcpy(a, b)    strcpy ((char *) a, (char *) b)
  185. #define icharcmp(a, b)    strcmp ((char *) a, (char *) b)
  186. #define icharncmp(a, b, n) strncmp ((char *) a, (char *) b, n)
  187. #define chartoichar(x)    ((ichar_t) (x))
  188. #else
  189. typedef unsigned short    ichar_t;    /* Internal character */
  190. #define chartoichar(x)    ((ichar_t) (unsigned char) (x))
  191. #endif
  192.  
  193. struct dent
  194.     {
  195.     struct dent *    next;
  196.     char *        word;
  197.     MASKTYPE        mask[MASKSIZE];
  198. #ifdef FULLMASKSET
  199.     char        flags;
  200. #endif
  201.     };
  202.  
  203. /*
  204. ** Flags in the directory entry.  If FULLMASKSET is undefined, these are
  205. ** stored in the highest bits of the last longword of the mask field.  If
  206. ** FULLMASKSET is defined, they are stored in the extra "flags" field.
  207. #ifndef NO_CAPITALIZATION_SUPPORT
  208. **
  209. ** If a word has only one capitalization form, and that form is not
  210. ** FOLLOWCASE, it will have exactly one entry in the dictionary.  The
  211. ** legal capitalizations will be indicated by the 2-bit capitalization
  212. ** field, as follows:
  213. **
  214. **    ALLCAPS        The word must appear in all capitals.
  215. **    CAPITALIZED    The word must be capitalized (e.g., London).
  216. **            It will also be accepted in all capitals.
  217. **    ANYCASE        The word may appear in lowercase, capitalized,
  218. **            or all-capitals.
  219. **
  220. ** Regardless of the capitalization flags, the "word" field of the entry
  221. ** will point to an all-uppercase copy of the word.  This is to simplify
  222. ** the large portion of the code that doesn't care about capitalization.
  223. ** Ispell will generate the correct version when needed.
  224. **
  225. ** If a word has more than one capitalization, there will be multiple
  226. ** entries for it, linked together by the "next" field.  The initial
  227. ** entry for such words will be a dummy entry, primarily for use by code
  228. ** that ignores capitalization.  The "word" field of this entry will
  229. ** again point to an all-uppercase copy of the word.  The "mask" field
  230. ** will contain the logical OR of the mask fields of all variants.
  231. ** A header entry is indicated by a capitalization type of ALLCAPS,
  232. ** with the MOREVARIANTS bit set.
  233. **
  234. ** The following entries will define the individual variants.  Each
  235. ** entry except the last has the MOREVARIANTS flag set, and each
  236. ** contains one of the following capitalization options:
  237. **
  238. **    ALLCAPS        The word must appear in all capitals.
  239. **    CAPITALIZED    The word must be capitalized (e.g., London).
  240. **            It will also be accepted in all capitals.
  241. **    FOLLOWCASE    The word must be capitalized exactly like the
  242. **            sample in the entry.  Prefix (suffix) characters
  243. **            must be rendered in the case of the first (last)
  244. **            "alphabetic" character.  It will also be accepted
  245. **            in all capitals.  ("Alphabetic" means "mentioned
  246. **            in a 'casechars' statement".)
  247. **    ANYCASE        The word may appear in lowercase, capitalized,
  248. **            or all-capitals.
  249. **
  250. ** The "mask" field for the entry contains only the affix flag bits that
  251. ** are legal for that capitalization.  The "word" field will be null
  252. ** except for FOLLOWCASE entries, where it will point to the
  253. ** correctly-capitalized spelling of the root word.
  254. **
  255. ** It is worth discussing why the ALLCAPS option is used in
  256. ** the header entry.  The header entry accepts an all-capitals
  257. ** version of the root plus every affix (this is always legal, since
  258. ** words get capitalized in headers and so forth).  Further, all of
  259. ** the following variant entries will reject any all-capitals form
  260. ** that is illegal due to an affix.
  261. **
  262. ** Finally, note that variations in the KEEP flag can cause a multiple-variant
  263. ** entry as well.  For example, if the personal dictionary contains "ALPHA",
  264. ** (KEEP flag set) and the user adds "alpha" with the KEEP flag clear, a
  265. ** multiple-variant entry will be created so that "alpha" will be accepted
  266. ** but only "ALPHA" will actually be kept.
  267. #endif
  268. */
  269. #ifdef FULLMASKSET
  270. #define flagfield    flags
  271. #else
  272. #define flagfield    mask[MASKSIZE - 1]
  273. #endif
  274. #define USED        ((MASKTYPE) 1 << (FLAGBASE + 0))
  275. #define KEEP        ((MASKTYPE) 1 << (FLAGBASE + 1))
  276. #ifdef NO_CAPITALIZATION_SUPPORT
  277. #define ALLFLAGS    (USED | KEEP)
  278. #else /* NO_CAPITALIZATION_SUPPORT */
  279. #define ANYCASE        ((MASKTYPE) 0 << (FLAGBASE + 2))
  280. #define ALLCAPS        ((MASKTYPE) 1 << (FLAGBASE + 2))
  281. #define CAPITALIZED    ((MASKTYPE) 2 << (FLAGBASE + 2))
  282. #define FOLLOWCASE    ((MASKTYPE) 3 << (FLAGBASE + 2))
  283. #define CAPTYPEMASK    ((MASKTYPE) 3 << (FLAGBASE + 2))
  284. #define MOREVARIANTS    ((MASKTYPE) 1 << (FLAGBASE + 4))
  285. #define ALLFLAGS    (USED | KEEP | CAPTYPEMASK | MOREVARIANTS)
  286. #define captype(x)    ((x) & CAPTYPEMASK)
  287. #endif /* NO_CAPITALIZATION_SUPPORT */
  288.  
  289. /*
  290.  * Language tables used to encode prefix and suffix information.
  291.  */
  292. struct flagent
  293.     {
  294.     ichar_t *        strip;            /* String to strip off */
  295.     ichar_t *        affix;            /* Affix to append */
  296.     short        flagbit;        /* Flag bit this ent matches */
  297.     short        stripl;            /* Length of strip */
  298.     short        affl;            /* Length of affix */
  299.     short        numconds;        /* Number of char conditions */
  300.     short        flagflags;        /* Modifiers on this flag */
  301.     char        conds[SET_SIZE + MAXSTRINGCHARS]; /* Adj. char conds */
  302.     };
  303.  
  304. /*
  305.  * Bits in flagflags
  306.  */
  307. #define FF_CROSSPRODUCT    (1 << 0)        /* Affix does cross-products */
  308. #define FF_COMPOUNDONLY    (1 << 1)        /* Afx works in compounds */
  309.  
  310. union ptr_union                    /* Aid for building flg ptrs */
  311.     {
  312.     struct flagptr *    fp;            /* Pointer to more indexing */
  313.     struct flagent *    ent;            /* First of a list of ents */
  314.     };
  315.  
  316. struct flagptr
  317.     {
  318.     union ptr_union    pu;            /* Ent list or more indexes */
  319.     int            numents;        /* If zero, pu.fp is valid */
  320.     };
  321.  
  322. /*
  323.  * Description of a single string character type.
  324.  */
  325. struct strchartype
  326.     {
  327.     char *        name;            /* Name of the type */
  328.     char *        deformatter;        /* Deformatter to use */
  329.     char *        suffixes;        /* File suffixes, null seps */
  330.     };
  331.  
  332. /*
  333.  * Header placed at the beginning of the hash file.
  334.  */
  335. struct hashheader
  336.     {
  337.     unsigned short magic;                        /* Magic number for ID */
  338.     unsigned short compileoptions;        /* How we were compiled */
  339.     short maxstringchars;            /* Max # strchrs we support */
  340.     short maxstringcharlen;            /* Max strchr len supported */
  341.     short compoundmin;                /* Min lth of compound parts */
  342.     short compoundbit;                /* Flag 4 compounding roots */
  343.     int stringsize;                /* Size of string table */
  344.     int lstringsize;                /* Size of lang. str tbl */
  345.     int tblsize;                /* No. entries in hash tbl */
  346.     int stblsize;                /* No. entries in sfx tbl */
  347.     int ptblsize;                /* No. entries in pfx tbl */
  348.     int sortval;                /* Largest sort ID assigned */
  349.     int nstrchars;                /* No. strchars defined */
  350.     int nstrchartype;                /* No. strchar types */
  351.     int strtypestart;                /* Start of strtype table */
  352.     char nrchars[5];                /* Nroff special characters */
  353.     char texchars[13];                /* TeX special characters */
  354.     char compoundflag;                /* Compund-word handling */
  355.     char defhardflag;                /* Default tryveryhard flag */
  356.     char flagmarker;                /* "Start-of-flags" char */
  357.     unsigned short sortorder[SET_SIZE + MAXSTRINGCHARS]; /* Sort ordering */
  358.     ichar_t lowerconv[SET_SIZE + MAXSTRINGCHARS]; /* Lower-conversion table */
  359.     ichar_t upperconv[SET_SIZE + MAXSTRINGCHARS]; /* Upper-conversion table */
  360.     char wordchars[SET_SIZE + MAXSTRINGCHARS]; /* NZ for chars found in wrds */
  361.     char upperchars[SET_SIZE + MAXSTRINGCHARS]; /* NZ for uppercase chars */
  362.     char lowerchars[SET_SIZE + MAXSTRINGCHARS]; /* NZ for lowercase chars */
  363.     char boundarychars[SET_SIZE + MAXSTRINGCHARS]; /* NZ for boundary chars */
  364.     char stringstarts[SET_SIZE];        /* NZ if char can start str */
  365.     char stringchars[MAXSTRINGCHARS][MAXSTRINGCHARLEN + 1]; /* String chars */
  366.     unsigned int stringdups[MAXSTRINGCHARS];    /* No. of "base" char */
  367.     int dupnos[MAXSTRINGCHARS];            /* Dup char ID # */
  368.     unsigned short magic2;            /* Second magic for dbl chk */
  369.     };
  370.  
  371. /* hash table magic number */
  372. #define MAGIC            0x9602
  373.  
  374. /* compile options, put in the hash header for consistency checking */
  375. #ifdef NO8BIT
  376. # define MAGIC8BIT        0x01
  377. #else
  378. # define MAGIC8BIT        0x00
  379. #endif
  380. #ifdef NO_CAPITALIZATION_SUPPORT
  381. # define MAGICCAPITALIZATION    0x00
  382. #else
  383. # define MAGICCAPITALIZATION    0x02
  384. #endif
  385. #if MASKBITS <= 32
  386. # define MAGICMASKSET        0x00
  387. #else
  388. # if MASKBITS <= 64
  389. #  define MAGICMASKSET        0x04
  390. # else
  391. #  if MASKBITS <= 128
  392. #   define MAGICMASKSET        0x08
  393. #  else
  394. #   define MAGICMASKSET        0x0C
  395. #  endif
  396. # endif
  397. #endif
  398.  
  399. #define COMPILEOPTIONS    (MAGIC8BIT | MAGICCAPITALIZATION | MAGICMASKSET)
  400.  
  401. /*
  402.  * Structure used to record data about successful lookups; these values
  403.  * are used in the ins_root_cap routine to produce correct capitalizations.
  404.  */
  405. struct success
  406.     {
  407.     struct dent *    dictent;    /* Header of dict entry chain for wd */
  408.     struct flagent *    prefix;        /* Prefix flag used, or NULL */
  409.     struct flagent *    suffix;        /* Suffix flag used, or NULL */
  410.     };
  411.  
  412. /*
  413. ** Offsets into the nroff special-character array
  414. */
  415. #define NRLEFTPAREN    hashheader.nrchars[0]
  416. #define NRRIGHTPAREN    hashheader.nrchars[1]
  417. #define NRDOT        hashheader.nrchars[2]
  418. #define NRBACKSLASH    hashheader.nrchars[3]
  419. #define NRSTAR        hashheader.nrchars[4]
  420.  
  421. /*
  422. ** Offsets into the TeX special-character array
  423. */
  424. #define TEXLEFTPAREN    hashheader.texchars[0]
  425. #define TEXRIGHTPAREN    hashheader.texchars[1]
  426. #define TEXLEFTSQUARE    hashheader.texchars[2]
  427. #define TEXRIGHTSQUARE    hashheader.texchars[3]
  428. #define TEXLEFTCURLY    hashheader.texchars[4]
  429. #define TEXRIGHTCURLY    hashheader.texchars[5]
  430. #define TEXLEFTANGLE    hashheader.texchars[6]
  431. #define TEXRIGHTANGLE    hashheader.texchars[7]
  432. #define TEXBACKSLASH    hashheader.texchars[8]
  433. #define TEXDOLLAR    hashheader.texchars[9]
  434. #define TEXSTAR        hashheader.texchars[10]
  435. #define TEXDOT        hashheader.texchars[11]
  436. #define TEXPERCENT    hashheader.texchars[12]
  437.  
  438. /*
  439. ** Values for compoundflag
  440. */
  441. #define COMPOUND_NEVER        0    /* Compound words are never good */
  442. #define COMPOUND_ANYTIME    1    /* Accept run-together words */
  443. #define COMPOUND_CONTROLLED    2    /* Compounds controlled by afx flags */
  444.  
  445. /*
  446. ** The isXXXX macros normally only check ASCII range, and don't support
  447. ** the character sets of other languages.  These private versions handle
  448. ** whatever character sets have been defined in the affix files.
  449. */
  450. #ifdef lint
  451. extern int    myupper P ((unsigned int ch));
  452. extern int    mylower P ((unsigned int ch));
  453. extern int    myspace P ((unsigned int ch));
  454. extern int    iswordch P ((unsigned int ch));
  455. extern int    isboundarych P ((unsigned int ch));
  456. extern int    isstringstart P ((unsigned int ch));
  457. extern ichar_t    mytolower P ((unsigned int ch));
  458. extern ichar_t    mytoupper P ((unsigned int ch));
  459. #else /* lint */
  460. #define myupper(X)    (hashheader.upperchars[X])
  461. #define mylower(X)    (hashheader.lowerchars[X])
  462. #define myspace(X)    (((X) > 0)  &&  ((X) < 0x80) \
  463.               &&  isspace((unsigned char) (X)))
  464. #define iswordch(X)    (hashheader.wordchars[X])
  465. #define isboundarych(X) (hashheader.boundarychars[X])
  466. #define isstringstart(X) (hashheader.stringstarts[(unsigned char) (X)])
  467. #define mytolower(X)    (hashheader.lowerconv[X])
  468. #define mytoupper(X)    (hashheader.upperconv[X])
  469. #endif /* lint */
  470.  
  471. /*
  472. ** These macros are similar to the ones above, but they take into account
  473. ** the possibility of string characters.  Note well that they take a POINTER,
  474. ** not a character.
  475. **
  476. ** The "l_" versions set "len" to the length of the string character as a
  477. ** handy side effect.  (Note that the global "laststringch" is also set,
  478. ** and sometimes used, by these macros.)
  479. **
  480. ** The "l1_" versions go one step further and guarantee that the "len"
  481. ** field is valid for *all* characters, being set to 1 even if the macro
  482. ** returns false.  This macro is a great example of how NOT to write
  483. ** readable C.
  484. */
  485. #define isstringch(ptr, canon)    (isstringstart (*ptr) \
  486.                   &&  stringcharlen (ptr, canon) > 0)
  487. #define l_isstringch(ptr, len, canon)    \
  488.                 (isstringstart (*ptr) \
  489.                   &&  (len = stringcharlen (ptr, canon)) > 0)
  490. #define l1_isstringch(ptr, len, canon)    \
  491.                 (len = 1, \
  492.                   isstringstart (*ptr) \
  493.                     &&  ((len = stringcharlen (ptr, canon)) \
  494.                     > 0 \
  495.                       ? 1 : (len = 1, 0)))
  496.  
  497. /*
  498.  * Sizes of buffers returned by ichartosstr/strtosichar.
  499.  */
  500. #define ICHARTOSSTR_SIZE (INPUTWORDLEN + 4 * MAXAFFIXLEN + 4)
  501. #define STRTOSICHAR_SIZE ((INPUTWORDLEN + 4 * MAXAFFIXLEN + 4) \
  502.               * sizeof (ichar_t))
  503.  
  504. /*
  505.  * termcap variables
  506.  */
  507. #ifdef MAIN
  508. # define EXTERN /* nothing */
  509. #else
  510. # define EXTERN extern
  511. #endif
  512.  
  513. EXTERN char *    BC;    /* backspace if not ^H */
  514. EXTERN char *    cd;    /* clear to end of display */
  515. EXTERN char *    cl;    /* clear display */
  516. EXTERN char *    cm;    /* cursor movement */
  517. EXTERN char *    ho;    /* home */
  518. EXTERN char *    nd;    /* non-destructive space */
  519. EXTERN char *    so;    /* standout */
  520. EXTERN char *    se;    /* standout end */
  521. EXTERN int    sg;    /* space taken by so/se */
  522. EXTERN char *    ti;    /* terminal initialization sequence */
  523. EXTERN char *    te;    /* terminal termination sequence */
  524. EXTERN int    li;    /* lines */
  525. EXTERN int    co;    /* columns */
  526.  
  527. EXTERN int    contextsize;    /* number of lines of context to show */
  528. EXTERN char    contextbufs[MAXCONTEXT][BUFSIZ]; /* Context of current line */
  529. EXTERN int    contextoffset;    /* Offset of line start in contextbufs[0] */
  530. EXTERN char *    currentchar;    /* Location in contextbufs */
  531. EXTERN char    ctoken[INPUTWORDLEN + MAXAFFIXLEN]; /* Current token as char */
  532. EXTERN ichar_t    itoken[INPUTWORDLEN + MAXAFFIXLEN]; /* Ctoken as ichar_t str */
  533.  
  534. EXTERN char    termcap[2048];    /* termcap entry */
  535. EXTERN char    termstr[2048];    /* for string values */
  536. EXTERN char *    termptr;    /* pointer into termcap, used by tgetstr */
  537.  
  538. EXTERN int    numhits;    /* number of hits in dictionary lookups */
  539. EXTERN struct success
  540.         hits[MAX_HITS]; /* table of hits gotten in lookup */
  541.  
  542. EXTERN char *    hashstrings;    /* Strings in hash table */
  543. EXTERN struct hashheader
  544.         hashheader;    /* Header of hash table */
  545. EXTERN struct dent *
  546.         hashtbl;    /* Main hash table, for dictionary */
  547. EXTERN int    hashsize;    /* Size of main hash table */
  548.  
  549. EXTERN char    hashname[MAXPATHLEN]; /* Name of hash table file */
  550.  
  551. EXTERN int    aflag;        /* NZ if -a or -A option specified */
  552. EXTERN int    cflag;        /* NZ if -c (crunch) option */
  553. EXTERN int    lflag;        /* NZ if -l (list) option */
  554. EXTERN int    incfileflag;    /* whether xgets() acts exactly like gets() */
  555. EXTERN int    nodictflag;    /* NZ if dictionary not needed */
  556. #ifdef AMIGA
  557. EXTERN int    rflag;        /* NZ if -r option specified */
  558. #endif /* AMIGA */
  559.  
  560. EXTERN int    uerasechar;    /* User's erase character, from stty */
  561. EXTERN int    ukillchar;    /* User's kill character */
  562.  
  563. EXTERN unsigned int laststringch; /* Number of last string character */
  564. EXTERN int    defdupchar;    /* Default duplicate string type */
  565.  
  566. EXTERN int    numpflags;        /* Number of prefix flags in table */
  567. EXTERN int    numsflags;        /* Number of suffix flags in table */
  568. EXTERN struct flagptr pflagindex[SET_SIZE + MAXSTRINGCHARS];
  569.                     /* Fast index to pflaglist */
  570. EXTERN struct flagent *    pflaglist;    /* Prefix flag control list */
  571. EXTERN struct flagptr sflagindex[SET_SIZE + MAXSTRINGCHARS];
  572.                     /* Fast index to sflaglist */
  573. EXTERN struct flagent *    sflaglist;    /* Suffix flag control list */
  574.  
  575. EXTERN struct strchartype *        /* String character type collection */
  576.         chartypes;
  577.  
  578. EXTERN FILE *    infile;            /* File being corrected */
  579. EXTERN FILE *    outfile;        /* Corrected copy of infile */
  580.  
  581. EXTERN char *    askfilename;        /* File specified in -f option */
  582.  
  583. EXTERN int    changes;        /* NZ if changes made to cur. file */
  584. EXTERN int    readonly;        /* NZ if current file is readonly */
  585. EXTERN int    quit;            /* NZ if we're done with this file */
  586.  
  587. #define MAXPOSSIBLE    100    /* Max no. of possibilities to generate */
  588.  
  589. EXTERN char    possibilities[MAXPOSSIBLE][INPUTWORDLEN + MAXAFFIXLEN];
  590.                 /* Table of possible corrections */
  591. EXTERN int    pcount;        /* Count of possibilities generated */
  592. EXTERN int    maxposslen;    /* Length of longest possibility */
  593. EXTERN int    easypossibilities; /* Number of "easy" corrections found */
  594.                 /* ..(defined as those using legal affixes) */
  595.  
  596. /*
  597.  * The following array contains a list of characters that should be tried
  598.  * in "missingletter."  Note that lowercase characters are omitted.
  599.  */
  600. EXTERN int    Trynum;        /* Size of "Try" array */
  601. EXTERN ichar_t    Try[SET_SIZE + MAXSTRINGCHARS];
  602.  
  603. /*
  604.  * Initialized variables.  These are generated using macros so that they
  605.  * may be consistently declared in all programs.  Numerous examples of
  606.  * usage are given below.
  607.  */
  608. #ifdef MAIN
  609. #define INIT(decl, init)    decl = init
  610. #else
  611. #define INIT(decl, init)    extern decl
  612. #endif
  613.  
  614. #ifdef MINIMENU
  615. INIT (int minimenusize, 2);        /* MUST be either 2 or zero */
  616. #else /* MINIMENU */
  617. INIT (int minimenusize, 0);        /* MUST be either 2 or zero */
  618. #endif /* MINIMENU */
  619.  
  620. INIT (int eflag, 0);            /* NZ for expand mode */
  621. INIT (int dumpflag, 0);            /* NZ to do dump mode */
  622. INIT (int fflag, 0);            /* NZ if -f specified */
  623. #ifndef USG
  624. INIT (int sflag, 0);            /* NZ to stop self after EOF */
  625. #endif
  626. INIT (int vflag, 0);            /* NZ to display characters as M-xxx */
  627. INIT (int xflag, DEFNOBACKUPFLAG);    /* NZ to suppress backups */
  628. INIT (int deftflag, -1);        /* NZ for TeX mode by default */
  629. INIT (int tflag, DEFTEXFLAG);        /* NZ for TeX mode in current file */
  630. INIT (int prefstringchar, -1);        /* Preferred string character type */
  631.  
  632. INIT (int terse, 0);            /* NZ for "terse" mode */
  633.  
  634. INIT (char tempfile[MAXPATHLEN], "");    /* Name of file we're spelling into */
  635.  
  636. INIT (int minword, MINWORD);        /* Longest always-legal word */
  637. INIT (int sortit, 1);            /* Sort suggestions alphabetically */
  638. INIT (int compoundflag, -1);        /* How to treat compounds: see above */
  639. INIT (int tryhardflag, -1);        /* Always call tryveryhard */
  640.  
  641. INIT (char * currentfile, NULL);    /* Name of current input file */
  642.  
  643. /* Odd numbers for math mode in LaTeX; even for LR or paragraph mode */
  644. INIT (int math_mode, 0);
  645. /* P -- paragraph or LR mode
  646.  * b -- parsing a \begin statement
  647.  * e -- parsing an \end statement
  648.  * r -- parsing a \ref type of argument.
  649.  * m -- looking for a \begin{minipage} argument.
  650.  */
  651. INIT (char LaTeX_Mode, 'P');
  652.